/**
 * 内存泄漏检测工具
 * 用于检测和报告内存泄漏问题
 */
export class MemoryLeakDetector {
  constructor() {
    this.components = new Map();
    this.eventListeners = new Map();
    this.timers = new Set();
    this.intervals = new Set();
    this.observers = new Set();
    this.domRefs = new Map();
    this.isEnabled = process.env.NODE_ENV === 'development';
  }

  /**
   * 注册组件
   * @param {string} componentName 组件名
   * @param {Object} component 组件实例
   */
  registerComponent(componentName, component) {
    if (!this.isEnabled) return;
    
    this.components.set(componentName, {
      instance: component,
      createdAt: Date.now(),
      eventListeners: new Set(),
      timers: new Set(),
      intervals: new Set(),
      observers: new Set(),
      domRefs: new Set()
    });
    
    console.log(`[MemoryLeakDetector] 注册组件: ${componentName}`);
  }

  /**
   * 注销组件
   * @param {string} componentName 组件名
   */
  unregisterComponent(componentName) {
    if (!this.isEnabled) return;
    
    const component = this.components.get(componentName);
    if (component) {
      // 检查是否有未清理的资源
      const warnings = [];
      
      if (component.eventListeners.size > 0) {
        warnings.push(`未清理的事件监听器: ${component.eventListeners.size}个`);
      }
      
      if (component.timers.size > 0) {
        warnings.push(`未清理的定时器: ${component.timers.size}个`);
      }
      
      if (component.intervals.size > 0) {
        warnings.push(`未清理的间隔器: ${component.intervals.size}个`);
      }
      
      if (component.observers.size > 0) {
        warnings.push(`未清理的观察器: ${component.observers.size}个`);
      }
      
      if (component.domRefs.size > 0) {
        warnings.push(`未清理的DOM引用: ${component.domRefs.size}个`);
      }
      
      if (warnings.length > 0) {
        console.warn(`[MemoryLeakDetector] 组件 ${componentName} 可能存在内存泄漏:`, warnings);
      } else {
        console.log(`[MemoryLeakDetector] 组件 ${componentName} 已正确清理`);
      }
      
      this.components.delete(componentName);
    }
  }

  /**
   * 记录事件监听器
   * @param {string} componentName 组件名
   * @param {string} event 事件名
   * @param {Function} handler 处理函数
   */
  recordEventListener(componentName, event, handler) {
    if (!this.isEnabled) return;
    
    const component = this.components.get(componentName);
    if (component) {
      const key = `${event}_${handler.name || 'anonymous'}`;
      component.eventListeners.add(key);
    }
  }

  /**
   * 移除事件监听器记录
   * @param {string} componentName 组件名
   * @param {string} event 事件名
   * @param {Function} handler 处理函数
   */
  removeEventListenerRecord(componentName, event, handler) {
    if (!this.isEnabled) return;
    
    const component = this.components.get(componentName);
    if (component) {
      const key = `${event}_${handler.name || 'anonymous'}`;
      component.eventListeners.delete(key);
    }
  }

  /**
   * 记录定时器
   * @param {string} componentName 组件名
   * @param {number} timerId 定时器ID
   */
  recordTimer(componentName, timerId) {
    if (!this.isEnabled) return;
    
    const component = this.components.get(componentName);
    if (component) {
      component.timers.add(timerId);
    }
  }

  /**
   * 移除定时器记录
   * @param {string} componentName 组件名
   * @param {number} timerId 定时器ID
   */
  removeTimerRecord(componentName, timerId) {
    if (!this.isEnabled) return;
    
    const component = this.components.get(componentName);
    if (component) {
      component.timers.delete(timerId);
    }
  }

  /**
   * 记录间隔器
   * @param {string} componentName 组件名
   * @param {number} intervalId 间隔器ID
   */
  recordInterval(componentName, intervalId) {
    if (!this.isEnabled) return;
    
    const component = this.components.get(componentName);
    if (component) {
      component.intervals.add(intervalId);
    }
  }

  /**
   * 移除间隔器记录
   * @param {string} componentName 组件名
   * @param {number} intervalId 间隔器ID
   */
  removeIntervalRecord(componentName, intervalId) {
    if (!this.isEnabled) return;
    
    const component = this.components.get(componentName);
    if (component) {
      component.intervals.delete(intervalId);
    }
  }

  /**
   * 记录观察器
   * @param {string} componentName 组件名
   * @param {Object} observer 观察器实例
   */
  recordObserver(componentName, observer) {
    if (!this.isEnabled) return;
    
    const component = this.components.get(componentName);
    if (component) {
      component.observers.add(observer);
    }
  }

  /**
   * 移除观察器记录
   * @param {string} componentName 组件名
   * @param {Object} observer 观察器实例
   */
  removeObserverRecord(componentName, observer) {
    if (!this.isEnabled) return;
    
    const component = this.components.get(componentName);
    if (component) {
      component.observers.delete(observer);
    }
  }

  /**
   * 记录DOM引用
   * @param {string} componentName 组件名
   * @param {string} refName 引用名
   * @param {Element} element DOM元素
   */
  recordDOMRef(componentName, refName, element) {
    if (!this.isEnabled) return;
    
    const component = this.components.get(componentName);
    if (component) {
      component.domRefs.add(refName);
    }
  }

  /**
   * 移除DOM引用记录
   * @param {string} componentName 组件名
   * @param {string} refName 引用名
   */
  removeDOMRefRecord(componentName, refName) {
    if (!this.isEnabled) return;
    
    const component = this.components.get(componentName);
    if (component) {
      component.domRefs.delete(refName);
    }
  }

  /**
   * 获取内存泄漏报告
   * @returns {Object} 报告信息
   */
  getReport() {
    const report = {
      totalComponents: this.components.size,
      componentsWithLeaks: 0,
      totalEventListeners: 0,
      totalTimers: 0,
      totalIntervals: 0,
      totalObservers: 0,
      totalDOMRefs: 0,
      details: []
    };

    this.components.forEach((component, name) => {
      const eventListeners = component.eventListeners.size;
      const timers = component.timers.size;
      const intervals = component.intervals.size;
      const observers = component.observers.size;
      const domRefs = component.domRefs.size;
      
      const hasLeaks = eventListeners > 0 || timers > 0 || intervals > 0 || observers > 0 || domRefs > 0;
      
      if (hasLeaks) {
        report.componentsWithLeaks++;
      }
      
      report.totalEventListeners += eventListeners;
      report.totalTimers += timers;
      report.totalIntervals += intervals;
      report.totalObservers += observers;
      report.totalDOMRefs += domRefs;
      
      report.details.push({
        name,
        hasLeaks,
        eventListeners,
        timers,
        intervals,
        observers,
        domRefs,
        createdAt: component.createdAt
      });
    });

    return report;
  }

  /**
   * 打印内存泄漏报告
   */
  printReport() {
    if (!this.isEnabled) return;
    
    const report = this.getReport();
    
    console.group('[MemoryLeakDetector] 内存泄漏检测报告');
    console.log(`总组件数: ${report.totalComponents}`);
    console.log(`有泄漏的组件数: ${report.componentsWithLeaks}`);
    console.log(`未清理的事件监听器: ${report.totalEventListeners}`);
    console.log(`未清理的定时器: ${report.totalTimers}`);
    console.log(`未清理的间隔器: ${report.totalIntervals}`);
    console.log(`未清理的观察器: ${report.totalObservers}`);
    console.log(`未清理的DOM引用: ${report.totalDOMRefs}`);
    
    if (report.componentsWithLeaks > 0) {
      console.warn('存在内存泄漏的组件:');
      report.details
        .filter(detail => detail.hasLeaks)
        .forEach(detail => {
          console.warn(`- ${detail.name}:`, {
            eventListeners: detail.eventListeners,
            timers: detail.timers,
            intervals: detail.intervals,
            observers: detail.observers,
            domRefs: detail.domRefs
          });
        });
    }
    
    console.groupEnd();
  }

  /**
   * 启用检测
   */
  enable() {
    this.isEnabled = true;
  }

  /**
   * 禁用检测
   */
  disable() {
    this.isEnabled = false;
  }
}

// 创建全局实例
export const memoryLeakDetector = new MemoryLeakDetector();

/**
 * Vue混入，用于自动内存泄漏检测
 */
export const MemoryLeakDetectorMixin = {
  created() {
    if (memoryLeakDetector.isEnabled) {
      memoryLeakDetector.registerComponent(this.$options.name || 'Anonymous', this);
    }
  },

  beforeDestroy() {
    if (memoryLeakDetector.isEnabled) {
      memoryLeakDetector.unregisterComponent(this.$options.name || 'Anonymous');
    }
  }
};

export default MemoryLeakDetector;
